package main

import (
	"fmt"
	"io"
	"net"
	"strconv"
	"sync"
	"time"
)

type Server struct {
	Ip   string
	Port int
	// 在线用户列表
	OnlineMap map[string]*User
	mapLock   sync.RWMutex
	// 消息广播的channel
	Message chan string
	logger  Logger
}

// NewServer 创建一个server接口
func NewServer(ip string, port int) *Server {
	server := &Server{
		Ip:        ip,
		Port:      port,
		OnlineMap: make(map[string]*User),
		Message:   make(chan string),
		logger:    Logger{},
	}
	return server
}

// Handle z处理连接业务请求
func (this *Server) Handle(conn net.Conn) {
	//有新用户连接
	user := NewUser(conn, this)
	// 用户上线处理
	user.Online()
	// 用户活跃检测
	isLive := make(chan bool)
	go func() {
		buf := make([]byte, 4096)
		for {
			n, err := conn.Read(buf)
			if n == 0 {
				// 下线用户
				user.Offline()
				return
			}

			if err != nil && err != io.EOF {
				this.logger.Error("connection read error --> " + err.Error())
				return
			}
			// 提取用户消息 去除\n
			msg := string(buf[:n-1])
			this.logger.Info("[recv] 服务端收到消息：" + msg + " ｜ 来源：" + user.Addr)
			user.DoMessage(msg)
			// 刷新用户活跃程度
			isLive <- true
		}
	}()
	// 当前阻塞
	for {
		select {
		case <-isLive:
			// 不执行任何操作
			//刷新下面的定时器
		case <-time.After(time.Second * 60 * 60):
			user.SendMsg("你已1小时未发送消息，系统将自动踢出请重新连接！")
			// 关闭用户通道
			close(user.C)
			// 关闭用户连接
			user.Conn.Close()
			// 删除在线用户
			user.server.mapLock.Lock()
			delete(user.server.OnlineMap, user.Name)
			user.server.mapLock.Unlock()
			this.logger.Notice("用户：" + user.Name + " 1小时未活跃，系统已主动断开连接！｜ 来源：" + user.Addr)
			//退出handle go程
			return
		}
	}

}

// 广播消息方法
func (this *Server) BroadCast(user *User, msg string) {
	sendMsg := "[" + user.Addr + "]" + user.Name + ":" + msg
	this.Message <- sendMsg
}

// 监听Message广播一旦有消息就广播给全部用户
func (this *Server) ListenManager() {
	for {
		msg := <-this.Message
		this.mapLock.Lock()
		for _, client := range this.OnlineMap {
			client.C <- msg
		}
		this.mapLock.Unlock()
	}
}

func (this *Server) Logo() {
	Success("  ________  ___       _______   _______ _____ ________  ___ ")
	Success(" |_   _|  \\/  |      /  ___\\ \\ / /  ___|_   _|  ___|  \\/  | ")
	Success("   | | | .  . |______\\ `--. \\ V /\\ `--.  | | | |__ | .  . | ")
	Success("   | | | |\\/| |______|`--. \\ \\ /  `--. \\ | | |  __|| |\\/| | ")
	Success("  _| |_| |  | |      /\\__/ / | | /\\__/ / | | | |___| |  | | ")
	Success("  \\___/\\_|  |_/      \\____/  \\_/ \\____/  \\_/ \\____/\\_|  |_/ ")
	Success("                                                            ")
	fmt.Println()
	Notice("作者：一季🌸落雨殇 ---- QQ：1647762341")
}

// 服务启动
func (this *Server) Start() {
	this.Logo()
	//创建监听端
	listener, err := net.Listen("tcp", fmt.Sprintf("%s:%d", this.Ip, this.Port))
	if err != nil {
		this.logger.Error("Server start filed --> " + err.Error())
		return
	}
	// 最后关闭
	defer listener.Close()

	// 开启广播消息管理
	go this.ListenManager()
	this.logger.Info("service start ok! (ip:" + this.Ip + " port:" + strconv.Itoa(this.Port) + ")")
	// 接受连接请求
	for {
		// 获取连接，阻塞模式
		conn, err := listener.Accept()
		if err != nil {
			this.logger.Error("listen accept err --> " + err.Error())
			continue
		}

		// 异步处理
		go this.logger.Notice("[recv] 你有一个新连接 --> " + conn.RemoteAddr().String())
		go this.Handle(conn)
	}
}
